﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace ConfigSaver
{
    /// <summary>
    /// Configg的用法是：
    /// <para>1.在类下定义对象 Configs config;</para>
    /// <para>2.在窗体load事件中生成对象config = new Configs(ConfigFileName,this);</para>
    /// <para>3.在窗体load事件中绑上要保存的控件 config.Add("变量含义",control);</para>
    /// <para>4.最后要进行配置加载 config.LoadConfig();</para>
    /// </summary>
    public class Configg
    {
#pragma warning disable CS0649 // 从未对字段“Configg.remenber”赋值，字段将一直保持其默认值 false
        private readonly bool remenber;
#pragma warning restore CS0649 // 从未对字段“Configg.remenber”赋值，字段将一直保持其默认值 false
        private Form form1;
        private string configFileName;
        /// <summary>
        /// 创建一个配置文件
        /// </summary>
        /// <param name="ConfigFileName">配置文件的文件名</param>
        /// <param name="form">要保存的控件所在的窗体</param>
        /// <param name="rememberFormSizeAndLocation">记住窗体大小和位置</param>
        /// <para>!!!一定要记得LoadConfig</para>
        public Configg(string ConfigFileName, Form form, bool rememberFormSizeAndLocation = false)
        {
            configFileName = ConfigFileName;
            form.FormClosing += new FormClosingEventHandler(form_FormClosing);
            //remenber = rememberFormSizeAndLocation;
            form1 = form;
        }
        private void form_FormClosing(object sender, EventArgs e)
        {
            SaveConfig();
        }
        /// <summary>
        /// 创建一个配置文件
        /// </summary>
        /// <param name="ConfigFileName">配置文件的文件名</param>
        /// <para>要记得在formclosing事件中SaveConfig()</para>
        public Configg(string ConfigFileName)
        {
            configFileName = ConfigFileName;
        }
        #region TextBox
        private List<TextBox> textBoxes = new List<TextBox>();
        /// <summary>
        /// 文本框值的注释
        /// </summary>
        private List<string> textBoxComments = new List<string>();    
        /// <param name="comment">注释文本</param>
        /// <param name="textBox">要保存的文本框</param>
        public void Add(string comment, TextBox textBox)
        {
            textBoxComments.Add(comment);
            textBoxes.Add(textBox);
        }
        /// <param name="comment">注释文本</param>
        /// <param name="textBox">要保存的文本框</param>
        /// <param name="defaultText">默认值，在配置文件不存在时，文本框填充该值</param>
        public void Add(string comment, TextBox textBox, string defaultText)
        {
            textBox.Text = defaultText;
            textBoxComments.Add(comment);
            textBoxes.Add(textBox);
        }



        List<limitTextBox> listlim = new List<limitTextBox>();
        /// <summary>
        /// 可以对文本框输入的值进行限制
        /// </summary>
        /// <param name="comment">注释文本</param>
        /// <param name="textBox">要保存的文本框</param>
        /// <param name="defaultText">默认值，在配置文件不存在时，文本框填充该值</param>
        /// <param name="lowerlimit">下限制值</param>
        /// <param name="uplimit">上限制值</param>
        public void Add(string comment, TextBox textBox, string defaultText, double lowerlimit, double uplimit)
        {
            textBox.Text = defaultText;
            textBoxComments.Add(comment);
            textBoxes.Add(textBox);
            limitTextBox lim = new limitTextBox(ref textBox, ref lowerlimit, ref uplimit);
            listlim.Add(lim);
        }
        class limitTextBox
        {
            TextBox tb;
            double up;
            double low;
            public limitTextBox(ref TextBox tbx, ref double lowerl, ref double upl)
            {
                tb = tbx;
                tb.TextChanged += new EventHandler(tb_TextChanged);
                up = upl;
                low = lowerl;
            }
            public void tb_TextChanged(object sender, EventArgs e)
            {
                try
                {
                    double t = Convert.ToDouble(tb.Text);
                    if (low <= t && t <= up)
                    {
                        tb.BackColor = Color.White;
                    }
                    else
                        tb.BackColor = Color.Red;
                }
                catch
                {
                    tb.BackColor = Color.Red;
                }
            }
        }
        #endregion
        #region CheckBox
        private List<CheckBox> checkBoxes = new List<CheckBox>();
        private List<string> checkBoxComments = new List<string>();
        public void Add(string comment, CheckBox checkBox)
        {
            checkBoxComments.Add(comment);
            checkBoxes.Add(checkBox);
        }
        public void Add(string comment, CheckBox checkBox, CheckState defaultCheckeState)
        {
            checkBox.CheckState = defaultCheckeState;
            checkBoxComments.Add(comment);
            checkBoxes.Add(checkBox);
        }
        public void Add(string comment, CheckBox checkBox, string defaultText, CheckState defaultCheckeState)
        {
            checkBox.CheckState = defaultCheckeState;
            checkBox.Text = defaultText;
            checkBoxComments.Add(comment);
            checkBoxes.Add(checkBox);
        }
        public void Add(string comment, CheckBox checkBox, string defaultText)
        {
            checkBox.Text = defaultText;
            checkBoxComments.Add(comment);
            checkBoxes.Add(checkBox);
        }
        #endregion        
        #region ColorButton
        private List<Button> colorButtons = new List<Button>();
        private List<string> colorButtonComments = new List<string>();
        /// <summary>
        /// </summary>
        /// <param name="comment">注释文本</param>
        /// <param name="ColorButton">设置颜色用的按钮</param>
        public void Add(int markNumber, Button ColorButton)
        {
            colorButtonComments.Add("color" + markNumber.ToString());
            colorButtons.Add(ColorButton);
            ColorButton.FlatStyle = FlatStyle.Flat;
            ColorButton.Text = "";
            ColorButton.Click += new EventHandler(ColorButton_Click);
        }
        /// <summary>
        /// </summary>
        /// <param name="comment">注释文本</param>
        /// <param name="ColorButton">设置颜色用的按钮</param>
        /// <param name="defaultColor">默认颜色</param>
        public void Add(int markNumber, Button ColorButton, Color defaultColor)
        {
            ColorButton.BackColor = defaultColor;
            colorButtonComments.Add("color" + markNumber.ToString());
            colorButtons.Add(ColorButton);
            ColorButton.Text = "";
            ColorButton.FlatStyle = FlatStyle.Flat;
            ColorButton.Click += new EventHandler(ColorButton_Click);
        }
        private void ColorButton_Click(object sender, EventArgs e)
        {
            ColorDialog cdg = new ColorDialog();
            cdg.Color = ((Button)sender).BackColor;
            cdg.ShowDialog();
            ((Button)sender).BackColor = cdg.Color;
        }
        #endregion
        #region FontButton
        private List<Button> fontButtons = new List<Button>();
        private List<string> fontButtonComments = new List<string>();
        /// <summary>
        /// </summary>
        /// <param name="comment">注释文本</param>
        /// <param name="FontButton">设置颜色用的按钮</param>
        public void Add(string comment, Button FontButton)
        {
            fontButtonComments.Add(comment);
            fontButtons.Add(FontButton);
            FontButton.FlatStyle = FlatStyle.Popup;
            FontButton.Text = "字体样式";
            FontButton.Click += new EventHandler(FontButton_Click);
        }
        /// <summary>
        /// </summary>
        /// <param name="comment">注释文本</param>
        /// <param name="FontButton">设置颜色用的按钮</param>
        /// <param name="defaultFont">默认颜色</param>
        public void Add(string comment, Button FontButton, Font defaultFont)
        {
            FontButton.Font = defaultFont;
            fontButtonComments.Add(comment);
            fontButtons.Add(FontButton);
            FontButton.Text = "字体样式";
            FontButton.FlatStyle = FlatStyle.Popup;
            FontButton.Click += new EventHandler(FontButton_Click);
        }
        private void FontButton_Click(object sender, EventArgs e)
        {
            FontDialog cdg = new FontDialog();
            cdg.ShowColor = true;
            cdg.Font = ((Button)sender).Font;
            cdg.Color = ((Button)sender).ForeColor;
            cdg.ShowDialog();
            ((Button)sender).Font = cdg.Font;
            ((Button)sender).ForeColor = cdg.Color;
        }
        #endregion
        #region DataGridView
        List<DataGridView> dvlist = new List<DataGridView>();
        public void Add(DataGridView dataGridView)
        {
            dvlist.Add(dataGridView);
        }
        #endregion
        #region RadioButton
        private List<RadioButton> radioButtons = new List<RadioButton>();
        private List<string> radioButtonComments = new List<string>();
        public void Add(RadioButton radioButton,bool defualtChecked)
        {
            radioButton.Checked = defualtChecked;
            radioButtonComments.Add(radioButton.Text);
            radioButtons.Add(radioButton);
        }
        public void Add(string comment, RadioButton radioButton)
        {
            radioButtonComments.Add(comment);
            radioButtons.Add(radioButton);
        }
        public void Add(string comment, RadioButton radioButton, bool defaultChecked)
        {
            radioButtonComments.Add(comment);
            radioButton.Checked = defaultChecked;
            radioButtons.Add(radioButton);
        }
        public void Add(string comment, RadioButton radioButton, string defaultText, bool defaultChecked)
        {
            radioButtonComments.Add(comment);
            radioButton.Text = defaultText;
            radioButton.Checked = defaultChecked;
            radioButtons.Add(radioButton);
        }
        public void Add(string comment, RadioButton radioButton, string defaultText)
        {
            radioButtonComments.Add(comment);
            radioButton.Text = defaultText;
            radioButtons.Add(radioButton);
        }
        #endregion
        #region comboBox
        private List<ComboBox> comboBoxes = new List<ComboBox>();
        public void Add(string comment, ComboBox comboBox,UInt16 defaultSeletIndex)
        {
            try
            {
                comboBox.SelectedIndex = defaultSeletIndex;
            }
            catch { }
            comboBoxes.Add(comboBox);
            comboBox.Name = comment;
        }
        #endregion
        /// <summary>
        /// 加载配置
        /// </summary>
        public void LoadConfig()
        {
            try
            {
                if (!File.Exists(configFileName))//如果配置文件不存在
                {
                    if ((Path.GetDirectoryName(configFileName) != "")
                        && (!Directory.Exists(Path.GetDirectoryName(configFileName))))//如果配置文件的目录不存在
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(configFileName));
                    }
                    SaveConfig();
                }
                StreamReader sr = new StreamReader(configFileName, Encoding.Default);
                string str;
                sr.ReadLine();
                sr.ReadLine();//跳过作者戳和时间戳
                for (int i = 0; i < textBoxes.Count; i++)
                {
                    str = sr.ReadLine(); if (str == "[配置结束]") goto end;
                    textBoxes[i].Text = str.Substring(str.IndexOf("=") + 1);
                    if (textBoxes[i].Text.Contains("\\r\\n")) textBoxes[i].Text = textBoxes[i].Text.Replace("\\r\\n", "\r\n");
                }
                for (int i = 0; i < checkBoxComments.Count; i++)
                {
                    str = sr.ReadLine(); if (str == "[配置结束]") goto end;
                    checkBoxes[i].CheckState = (str.Substring(str.IndexOf("=") + 1) == "Checked" ? CheckState.Checked
                        : (str.Substring(str.IndexOf("=") + 1) == "Unchecked" ? CheckState.Unchecked : CheckState.Indeterminate));
                }
                for (int i = 0; i < colorButtons.Count; i++)
                {
                    str = sr.ReadLine(); if (str == "[配置结束]") goto end;
                    string[] rgb = str.Substring(str.IndexOf("=") + 1).Split(',');
                    if (rgb.Length != 3) goto end;
                    colorButtons[i].BackColor = Color.FromArgb(Convert.ToInt32(rgb[0]), Convert.ToInt32(rgb[1]), Convert.ToInt32(rgb[2]));
                }
                for (int i = 0; i < radioButtons.Count; i++)
                {
                    str = sr.ReadLine(); if (str == "[配置结束]") goto end;
                    radioButtons[i].Checked = (str.Substring(str.IndexOf("=") + 1) == "True" ? true : false);
                }
                for (int i = 0; i < comboBoxes.Count; i++)
                {
                    str = sr.ReadLine(); if (str == "[配置结束]") goto end;
                    try
                    {
                        comboBoxes[i].SelectedIndex = Convert.ToUInt16(str.Substring(str.IndexOf("=") + 1));
                    }
                    catch (Exception er) { Console.WriteLine(er.Message); }
                }
                for (int i = 0; i < fontButtons.Count; i++)
                {
                    str = sr.ReadLine(); if (str == "[配置结束]") goto end;
                    string[] f = str.Substring(str.IndexOf("=") + 1).Split('|');
                    string[] rgb = f[3].Trim().Split(',');
                    FontStyle fs = new FontStyle();
                    if (f[1].Contains("Regular"))
                        fs |= FontStyle.Regular;
                    if (f[1].Contains("Bold"))
                        fs |= FontStyle.Bold;
                    if (f[1].Contains("Italic"))
                        fs |= FontStyle.Italic;
                    if (f[1].Contains("Strikeout"))
                        fs |= FontStyle.Strikeout;
                    if (f[1].Contains("Underline"))
                        fs |= FontStyle.Underline;
                    fontButtons[i].ForeColor = Color.FromArgb(Convert.ToInt32(rgb[0]), Convert.ToInt32(rgb[1]), Convert.ToInt32(rgb[2]));
                    fontButtons[i].Font = new Font(f[0], Convert.ToSingle(f[2]), fs);
                }
                if (remenber)
                {
                    str = sr.ReadLine(); string[] f = str.Substring(str.IndexOf("=") + 1).Split(','); if (str == "[配置结束]" || f.Length != 4) goto end;
                    form1.Size = new Size(Convert.ToInt32(f[0]), Convert.ToInt32(f[1]));//保存窗体大小
                    form1.Location = new Point(Convert.ToInt32(f[2]), Convert.ToInt32(f[3]));//位置
                }
            end:
                sr.Dispose();
                sr.Close();
            }
            catch (SyntaxErrorException e)
            {
                MessageBox.Show(string.Format("哦，出了点问题！请把{0}文件删除再运行本程序\r\n{1}\r\n" ,configFileName, e.Message));
                File.Delete(configFileName);
            }
            string xmlFileName ="";
            try
            {
                foreach (DataGridView dv in dvlist)
                {
                    DataTable dt = (dv.DataSource as DataTable);
                    xmlFileName = Path.GetFileNameWithoutExtension(configFileName) + "_" + dv.Name + ".xml";
                    dt.WriteXml(xmlFileName);
                }
            }
            catch (SyntaxErrorException e)
            {
                MessageBox.Show(string.Format("哦，出了点问题！请把{0}文件删除再运行本程序\r\n{1}\r\n" ,xmlFileName, e.Message));
                File.Delete(xmlFileName);
            }
        }
        public void SaveConfig()
        {
            try
            {
                StreamWriter sw = new StreamWriter(configFileName, false, Encoding.UTF8);
                sw.WriteLine("[Mushily@foxmail.com]");
                sw.WriteLine("[" + System.DateTime.Now.ToString() + "]");
                for (int i = 0; i < textBoxes.Count; i++)
                {
                    string s = textBoxes[i].Text.Contains("\r\n") ? textBoxes[i].Text.Replace("\r\n", "\\r\\n") : textBoxes[i].Text;
                    sw.WriteLine("{0}={1}", textBoxComments[i], s);
                }
                for (int i = 0; i < checkBoxes.Count; i++)
                {
                    sw.WriteLine("{0}={1}", checkBoxComments[i], checkBoxes[i].CheckState);
                }
                for (int i = 0; i < colorButtons.Count; i++)
                {
                    sw.WriteLine("{0}={1},{2},{3}", colorButtonComments[i], colorButtons[i].BackColor.R, colorButtons[i].BackColor.G, colorButtons[i].BackColor.B);
                }
                for (int i = 0; i < radioButtons.Count; i++)
                {
                    sw.WriteLine("{0}={1}", radioButtonComments[i], radioButtons[i].Checked);
                }
                for (int i = 0; i < comboBoxes.Count; i++)
                {
                    try { sw.WriteLine("{0}={1}", comboBoxes[i].Name, comboBoxes[i].SelectedIndex); }
                    catch (Exception er) { Console.WriteLine(er.Message); Console.ReadLine(); sw.WriteLine("ErrorLine=0"); }
                }
                for (int i = 0; i < fontButtons.Count; i++)
                {
                    sw.WriteLine("{0}={1}|{2}|{3}|{4},{5},{6}", fontButtonComments[i], fontButtons[i].Font.Name, fontButtons[i].Font.Style, fontButtons[i].Font.Size
                        , fontButtons[i].ForeColor.R, fontButtons[i].ForeColor.G, fontButtons[i].ForeColor.B);
                }
                if (remenber)
                {
                    sw.WriteLine("Form={0},{1},{2},{3}", form1.Width, form1.Height, form1.Location.X, form1.Location.Y);
                }
                sw.Write("[配置结束]");
                sw.Dispose();
                sw.Close();
            }
            catch
            {
                MessageBox.Show("再次强调，请先将配置文件删除重试，建议不要尝试自行修改配置文件");
            }
        }
        ~Configg()
        {
            textBoxes.Clear();
            textBoxComments.Clear();
            colorButtons.Clear();
            colorButtonComments.Clear();
            fontButtons.Clear();
            fontButtonComments.Clear();
            checkBoxes.Clear();
            checkBoxComments.Clear();
            radioButtons.Clear();
            radioButtonComments.Clear();
            comboBoxes.Clear();
            configFileName = null;
        }
    }
}
